package tomasulo.component;

import tomasulo.Driver;
import tomasulo.unit.Instr;

public class Adder extends Component {

	private Instr.OP op = Instr.OP.NOOP;
	private Register op1 = null;
	private Register op2 = null;
	private static final int TIME_DELAY = 2;
	private Float result = null;

	public Adder(String name) {
		super(name);
		op1 = new Register(name + "op1");
		op2 = new Register(name + "op2");
	}

	@Override
	public void afterTick(int tick) {
		if (busy) {
			if (time > 0) {
				--time;
				if (time == 0) {
					if (op.equals(Instr.OP.ADDD))
						result = new Float(op1.getValue() + op2.getValue());
					else if (op.equals(Instr.OP.SUBD))
						result = new Float(op1.getValue() - op2.getValue());
					instr.setTimeComp(tick);
				}
			} else if (time == 0) {
				instr.setTimeWrite(tick);
				Driver.putCDB(name, result);
				reset();
			}
		}
	}

	@Override
	public void checkCDB(int tick) {
		if (busy && (time == TIME_WAIT)) {
			op1.checkCDB(tick);		
			op2.checkCDB(tick);
			if (op1.isReady() && op2.isReady()) {
				time = TIME_DELAY;
			}
		}
	}

	@Override
	public boolean issue(Instr instr) {
		if (busy)
			return false;
		if (!instr.op.equals(Instr.OP.ADDD) && !instr.op.equals(Instr.OP.SUBD))
			return false;
		this.instr = instr;
		op1.copyFromFU(instr.op1);
		op2.copyFromFU(instr.op2);			
		Driver.getFU().get(instr.op0).setStation(name);
		busy = true;
		this.op = instr.op;
		if (op1.isReady() && op2.isReady())
			time = TIME_DELAY;
		else
			time = TIME_WAIT; 
		return true;
	}
	
	public Register getOp1() {
		return op1;
	}

	public Register getOp2() {
		return op2;
	}

	public Instr.OP getOp() {
		return op;
	}

	public Float getResult() {
		return result;
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
		busy = false;
		op1.setValue(0);
		op2.setValue(0);
		op = Instr.OP.NOOP;
		result = null;
		time = 0;
	}

}
